﻿using Kingdee.BOS.Core.Bill;
using Kingdee.BOS.Core.DynamicForm;
using Kingdee.BOS.Core;
using Kingdee.BOS;
using Kingdee.BOS.Core.DynamicForm.PlugIn;
using Kingdee.BOS.Core.DynamicForm.PlugIn.Args;
using Kingdee.BOS.Core.Metadata.FieldElement;
using Kingdee.BOS.ServiceHelper;
using Kingdee.BOS.Util;
using RK.Tools;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Kingdee.BOS.Orm.DataEntity;
using RK.Model;
using Newtonsoft.Json;
using RK.Model.FanWei;
using System.Threading;
using Kingdee.BOS.Orm;
using Kingdee.BOS.JSON;
using Kingdee.BOS.Workflow.ServiceHelper;
using Kingdee.BOS.Workflow.Models.Chart;
using RK.Model.Ronma;

namespace RK.SerivesPlugin.Ronma
{
    [Description("金蝶和第三方系统同步通用服务插件")]
    [HotUpdate]
    public class ServicePlugnKAndOSysSyn : AbstractOperationServicePlugIn
    {
        public override void EndOperationTransaction(EndOperationTransactionArgs e)
        {
            base.EndOperationTransaction(e);
            string formId = this.BusinessInfo.GetForm().Id;
            if (e.DataEntitys.Count() <= 0)
            {
                return;
            }
            //获取主业务组织
            OrgField orgField = this.BusinessInfo.MainOrgField;
            //组织-业务数据字典
            Dictionary<long, List<DynamicObject>> orgAndOrders = new Dictionary<long, List<DynamicObject>>();
            //主业务组织不为空按组织分组
            if (orgField != null)
            {
                orgAndOrders = e.DataEntitys.GroupBy(g => Convert.ToInt64((orgField.GetFieldValue(g) as DynamicObject)["id"])).ToDictionary(t => t.Key, t => t.ToList());
            }
            //取当前组织
            else
            {
                orgAndOrders.Add(this.Context.CurrentOrganizationInfo.ID, e.DataEntitys.ToList());
            }

            string formName = this.BusinessInfo.GetForm().Name;
            string OperationName = this.FormOperation.OperationName.GetString(2052);
            string OperationNumber = this.FormOperation.Operation;
            IBillView view = KingdeeTools.CreateBillView(this.Context, formId);
            OperateResultCollection orc = new OperateResultCollection();
            //结果对象
            List<DynamicObject> saveOrders = e.DataEntitys.ToList();
            List<DynamicObject> changeOrders = new List<DynamicObject>();
            foreach (long orgId in orgAndOrders.Keys)
            {
                List<DynamicObject> kToOSysSynOps = KAndOSysSynTool.GetKToOSysSynOps(this.Context, formId, orgId, this.FormOperation.Operation, 4);
                if (kToOSysSynOps == null || kToOSysSynOps.Count() == 0)
                {
                    continue;
                }
                else
                {
                    //获取同步设置和URL
                    DynamicObject setting = KAndOSysSynTool.GetKToOSysSynSetting(this.Context, formId, orgId);
                    if (setting == null)
                    {
                        continue;
                    }
                    List<DynamicObject> orders = orgAndOrders[orgId];
                    foreach (var order in orders)
                    {
                        view.Model.DataObject = order;
                        DynamicObject kToOSysSynOp = GetSatisfyConditionOp(view, kToOSysSynOps, OperationName);
                        if (kToOSysSynOp == null)
                        {
                            continue;
                        }
                        else
                        {
                            string port = Convert.ToString(kToOSysSynOp["Port"]);
                            string url = KAndOSysSynTool.GetUrl(setting, port);
                            string appkey = Convert.ToString(setting["FOSysURL2"]);
                            var userinfo = this.Context.UserId;
                            bool isOk = KingdeeTools.IsStringInEnum(formId, typeof(FormIdEnum.ServiceList));
                            if (!isOk)
                            {
                                return;
                            }

                            bool isSuccess = SynOSys(formId, formName, view, orc, OperationName, kToOSysSynOp, url, orgId, changeOrders, appkey);
                            if (!isSuccess)
                            {
                                saveOrders.Remove(order);
                            }
                        }
                    }
                }
            }
            foreach (var o in orc)
            {
                this.OperationResult.OperateResult.Add(o);
            }
            //存在失败，全部失败
            if (saveOrders.Count() != e.DataEntitys.Count())
            {
                string msg = string.Join("\r\n", orc.Where(w => w.MessageType != MessageType.Normal).Select(s => s.Message));
                throw new KDException("RK", msg);
            }
            //保存修改的数据
            if (changeOrders.Count() > 0)
            {
                BusinessDataServiceHelper.Save(this.Context, changeOrders.ToArray());
            }
        }

        private bool SynOSys(string formId, string formName, IBillView view, OperateResultCollection orc, string OperationName, DynamicObject kToOSysSynOp, string url, long orgId, List<DynamicObject> changeOrders, string appkey)
        {
            if (formId == FormIdEnum.ServiceList.PUR_PurchaseOrder.GetString())
            {
                UpdatePurOrderQty(view);
            }
            string billNo = Convert.ToString(view.BusinessInfo.GetBillNoField().GetFieldValue(view.Model.DataObject));
            object id = view.Model.DataObject["id"];
            //CreatorId FCREATORID
            int creatorId = 0;// 
            if (view.Model.DataObject.Contains("CreatorId"))
            {
                DynamicObject userObj = view.Model.DataObject["CreatorId"] as DynamicObject;
                creatorId = userObj == null ? 0 : Convert.ToInt32(userObj["Id"]);
            }
            else
            {
                if (view.Model.DataObject.Contains("FCreatorId"))
                {
                    DynamicObject userObj = view.Model.DataObject["FCreatorId"] as DynamicObject;
                    creatorId = userObj == null ? 0 : Convert.ToInt32(userObj["Id"]);
                }
            }
            if (view.Model.DataObject.Contains("FCreaterId"))
            {
                DynamicObject userObj = view.Model.DataObject["FCreaterId"] as DynamicObject;
                creatorId = userObj == null ? 0 : Convert.ToInt32(userObj["Id"]);
            }
            string creator = KingdeeTools.GetCreator(this.Context, creatorId);
            string msg = "";
            //OA单据ID
            int requestId = 0;
            if (view.Model.DataObject.Contains("FOAId"))
            {
                if (!view.Model.DataObject["FOAId"].IsNullOrEmptyOrWhiteSpace())
                {
                    requestId = Convert.ToInt32(view.Model.DataObject["FOAId"]);
                }
            }
            //采购订单新变更单
            if (formId.EqualsIgnoreCase("PUR_POXChange"))
            {
                if (view.Model.DataObject.Contains("FOAId2"))
                {
                    if (!view.Model.DataObject["FOAId2"].IsNullOrEmptyOrWhiteSpace())
                    {
                        requestId = Convert.ToInt32(view.Model.DataObject["FOAId2"]);
                    }
                }
            }
            //采购合同变更单
            if (formId.EqualsIgnoreCase("PUR_ContractChange"))
            {
                if (view.Model.DataObject.Contains("FOAId2"))
                {
                    if (!view.Model.DataObject["FOAId2"].IsNullOrEmptyOrWhiteSpace())
                    {
                        requestId = Convert.ToInt32(view.Model.DataObject["FOAId2"]);
                    }
                }
            }
            //CRM_XContract销售合同变更单
            if (formId.EqualsIgnoreCase("CRM_XContract"))
            {
                if (view.Model.DataObject.Contains("FOAId2"))
                {
                    if (!view.Model.DataObject["FOAId2"].IsNullOrEmptyOrWhiteSpace())
                    {
                        requestId = Convert.ToInt32(view.Model.DataObject["FOAId2"]);
                    }
                }
            }
            //销售订单新变更单
            if (formId.EqualsIgnoreCase("SAL_XORDER"))
            {
                if (view.Model.DataObject.Contains("FOAId2"))
                {
                    if (!view.Model.DataObject["FOAId2"].IsNullOrEmptyOrWhiteSpace())
                    {
                        requestId = Convert.ToInt32(view.Model.DataObject["FOAId2"]);
                    }
                }
            }
            //int requestId = view.Model.DataObject["FOAId"] == null ? 0 : Convert.ToInt32(view.Model.DataObject["FOAId"]);
            //OA的流程ID
            int workflowId = Convert.ToInt32(kToOSysSynOp["FworkflowId"]);
            //是否记录同步日志
            bool isRecordSynLog = Convert.ToBoolean(kToOSysSynOp["IsRecordSynLog"]);
            //同步类型:1状态，2数据
            string isSynType = Convert.ToString(kToOSysSynOp["IsSynType"]);
            //判断走新增还是修改接口
            var FPrecondition = Convert.ToString(kToOSysSynOp["FPrecondition"]);
            string jsonStr = "";
            //是否已记录过日志
            bool isRecord = false;
            bool returnResult = true;
            try
            {
                if (kToOSysSynOp != null)
                {
                    //同步映射配置
                    long kAndOSysSynMapId = Convert.ToInt64(kToOSysSynOp["KAndOSysSynMapId_id"]);
                    if (kAndOSysSynMapId > 0)
                    {
                        DynamicObject map = KingdeeTools.GetDynamicObjectByFormIdAndId(this.Context, "qqq_KAndOSysSynMap", kAndOSysSynMapId);
                        JSONObject json = new JSONObject();
                        if (isSynType.EqualsIgnoreCase("1"))
                        {

                        }
                        else
                        {
                            var conJson = KAndOSysSynTool.GetObjByK3(view, map);
                            json = KingdeeTools.ConvertOAJSON(conJson, FPrecondition, requestId);
                            json.Put("workflowId", workflowId);
                            json.Put("requestName", formName + ":" + billNo);
                            //如果修改接口，添加requestId
                            //if (FPrecondition != "FIsSubSynOA=true")
                            //{

                            //}
                        }

                        //同步数据的方式实现消息提示，金蝶一个节点存在多个处理人，发送给所有处理人不在该插件处理
                        if (isSynType.EqualsIgnoreCase("1") && OperationName == "提交")
                        {
                            //var activityCollection = this.Option.GetVariableValue<ObjectActivityInstanceCollection>(BOSConst.CST_KEY_WfActivityInstance, null);

                            //追加工作流信息
                            ////根据单据id获取流程实例id列表
                            //List<string> procInstIds = Kingdee.BOS.Workflow.ServiceHelper.ProcManageServiceHelper.GetPrcInstIdsByBillId(this.Context, formId, id.ToString());
                            //string cprocInstId = Kingdee.BOS.Workflow.ServiceHelper.WorkflowChartServiceHelper.GetProcInstIdByBillInst(this.Context, formId, id.ToString());
                            ////根据流程实例id获取当前处理人；
                            //var receivers = Kingdee.BOS.Workflow.ServiceHelper.BOSWorkflowServiceHelper.GetAllReceivers(this.Context, cprocInstId);
                            ////根据流程实例id获取审批路线，审批路线是1个节后，包括各个节点的消息；
                            //foreach (var procInstId in procInstIds)
                            //{
                            //    List<ChartActivityInfo> activityInfos = WorkflowChartServiceHelper.GetProcessRouter(this.Context, procInstId);
                            //}
                            //先获取金蝶地址
                            string kingdeeUrl = KingdeeTools.GetRequestWebUrl();
                            Timer timer = new Timer(args =>
                            {
                                try
                                {

                                    //获取当前最新流程实例id
                                    string cprocInstId = WorkflowChartServiceHelper.GetProcInstIdByBillInst(this.Context, formId, id.ToString());
                                    if (!cprocInstId.IsNullOrEmptyOrWhiteSpace())
                                    {
                                        //流程实例
                                        DynamicObject procInst = KingdeeTools.GetDynamicObjectByFormIdAndId(this.Context, "WF_ProcInstBill", cprocInstId);
                                        //流程模板
                                        DynamicObject tmp = KingdeeTools.GetDynamicObjectByFormIdAndId(this.Context, "wf_TemplateSelect", procInst["FTmpId_id"]);
                                        //类型
                                        string processType = Convert.ToString(tmp["ProcessType"]);
                                        List<ChartActivityInfo> activityInfos = WorkflowChartServiceHelper.GetProcessRouter(this.Context, cprocInstId);
                                        ChartActivityInfo firtActivityInfo = activityInfos.First();
                                        ChartActivityInfo chartActivityInfo = activityInfos.Last();
                                        if (chartActivityInfo.ActionDetails.Count() > 0)
                                        {
                                            DBResult result = new DBResult();
                                            foreach (ChartActionInfo chartActionInfo in chartActivityInfo.ActionDetails)
                                            {
                                                try
                                                {
                                                    string curFlowId = formName + chartActionInfo.AssignId + chartActionInfo.ActInstId;
                                                    string sourceId = formName + chartActivityInfo.SourceActivityName;
                                                    string curId = formName + chartActivityInfo.ActivityName;
                                                    //流程数据【标题】检测isremark不合法（0：待办|2：已办|4：办结|8：抄送）"}
                                                    //检测viewtype不合法（0：未读|1：已读）"}
                                                    //string workcode = "ZJRM0313";
                                                    string revId = chartActionInfo.Receivers;
                                                    string sWorkCode = KAndOSysSynTool.GetWorkCode(this.Context, this.Context.UserId.ToString());
                                                    string workcode = KAndOSysSynTool.GetWorkCode(this.Context, revId);
                                                    //string userName = chartActionInfo.ReceiverName;
                                                    string userName = this.Context.UserName;
                                                    string timestamp = GetTimestamp();
                                                    JSONObject cJson = json.DeepClone();
                                                    cJson.Add("syscode", "ERP");
                                                    cJson.Add("flowid", curFlowId);
                                                    cJson.Add("requestname", $"{creator}发起的{formName}:{billNo}审批流需要您处理！");
                                                    //cJson.Add("requestname", chartActionInfo.Title);
                                                    cJson.Add("workflowname", $"{formName}审批流");
                                                    cJson.Add("nodename", chartActivityInfo.ActivityName);
                                                    cJson.Add("receiver", workcode);
                                                    cJson.Add("creator", creator);
                                                    cJson.Add("createdatetime", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                                                    cJson.Add("receivedatetime", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                                                    //cJson.Add("appurl", KingdeeTools.GetMobileUrl(chartActionInfo.ReceiverName, chartActionInfo.AssignId, kingdeeUrl, this.Context));
                                                    //cJson.Add("pcurl", KingdeeTools.GetH5KindeeUrl(chartActionInfo.ReceiverName, chartActionInfo.AssignId, kingdeeUrl, processType, this.Context));
                                                    //var par = JsonConvert.SerializeObject(new { usserName = chartActionInfo.ReceiverName, pkid = chartActionInfo.AssignId });
                                                    //cJson.Add("appurl", par);
                                                    //cJson.Add("pcurl", par);
                                                    cJson.Add("appurl", chartActionInfo.AssignId);
                                                    cJson.Add("pcurl", chartActionInfo.AssignId);
                                                    cJson.Add("receivets", timestamp);
                                                    cJson.Add("isremark", "0");
                                                    cJson.Add("viewtype", "0");
                                                    jsonStr = cJson.ToString();
                                                    //string appkey = "6542f75b3ae42843dec9ee36";
                                                    result = InvokeHelper.Post(url, jsonStr, appkey, workcode, 0);
                                                    //msg = result.ErrMsg.ToString();
                                                    msg = JsonConvert.SerializeObject(result);// result.ToString();
                                                    //接口返回错误，终止循环
                                                    if (result.operResult != "1")
                                                    {
                                                        break;
                                                    }
                                                }
                                                catch (Exception er)
                                                {
                                                    msg = string.Format("【{0}】{1}【{2}】同步失败！错误信息：{3}"
                                                    , OperationName
                                                    , formName
                                                    , billNo
                                                    , er.Message);
                                                    orc.Add(new OperateResult()
                                                    {
                                                        PKValue = id
                                                        ,
                                                        Number = billNo
                                                        ,
                                                        Message = msg
                                                        ,
                                                        MessageType = MessageType.FatalError
                                                        ,
                                                        SuccessStatus = false
                                                    });
                                                    break;
                                                }
                                                finally
                                                {
                                                    //操作日志只记录一条
                                                    if (result.operResult == "1")
                                                    {
                                                        UpAssignIsSync(chartActionInfo.AssignId);
                                                        msg = string.Format("Service1:【{0}】{1}【{2}】成功，第三方系统返回信息：{3}！JSON信息：{4}"
                                                        , OperationName
                                                        , formName
                                                        , billNo
                                                        , msg
                                                        , json.ToString());
                                                        orc.Add(new OperateResult()
                                                        {
                                                            PKValue = id
                                                            ,
                                                            Number = billNo
                                                            ,
                                                            Message = msg,
                                                            MessageType = MessageType.Normal,
                                                            SuccessStatus = true
                                                        });
                                                        //同步结束回写映射配置
                                                        long retKToOSysSynMapId = Convert.ToInt64(kToOSysSynOp["RetKToOSysSynMapId_id"]);
                                                        if (retKToOSysSynMapId > 0)
                                                        {
                                                            DynamicObject retMap = KingdeeTools.GetDynamicObjectByFormIdAndId(this.Context, "qqq_KAndOSysSynMap", retKToOSysSynMapId);
                                                            JSONObject obj = JSONObject.Parse(JsonUtil.Serialize(result.message));
                                                            KAndOSysSynTool.SetViewValueByReturnResult(view, retMap, obj, FPrecondition, requestId);
                                                            changeOrders.Add(view.Model.DataObject);
                                                        }
                                                        returnResult = true;
                                                    }
                                                    else
                                                    {
                                                        msg = string.Format("Service2:【{0}】{1}【{2}】同步失败，第三方系统返回信息：{3}！JSON信息：{4}"
                                                        , OperationName
                                                        , formName
                                                        , billNo
                                                        , msg
                                                        , json.ToString());
                                                        orc.Add(new OperateResult()
                                                        {
                                                            PKValue = id
                                                            ,
                                                            Number = billNo
                                                            ,
                                                            Message = msg,
                                                            MessageType = MessageType.FatalError,
                                                            SuccessStatus = false
                                                        });
                                                        returnResult = false;
                                                    }
                                                }

                                            }

                                        }
                                        else
                                        {
                                            msg = string.Format("Service:流程实例ID【{0}】没有动作！请检查工作流！", cprocInstId);
                                            orc.Add(new OperateResult()
                                            {
                                                PKValue = id
                                                ,
                                                Number = billNo
                                                ,
                                                Message = msg,
                                                MessageType = MessageType.FatalError,
                                                SuccessStatus = false
                                            });
                                            returnResult = false;
                                        }
                                    }
                                    else
                                    {
                                        returnResult = true;
                                    }
                                }
                                catch (Exception er)
                                {
                                    msg = string.Format("Service:【{0}】{1}【{2}】同步失败！错误信息：{3}"
                                    , OperationName
                                    , formName
                                    , billNo
                                    , er.Message);
                                }
                                finally
                                {
                                    SyncLog log = new SyncLog();
                                    log.Operation = OperationName;
                                    log.FormId = formId;
                                    log.FbillName = formName;
                                    log.FBillNo = billNo;
                                    log.Result = msg;
                                    log.FOrgId = orgId;
                                    log.Json = jsonStr;
                                    log.Direction = creatorId.ToString();
                                    log.IsSuccess = returnResult;
                                    KingdeeTools.SaveLog(this.Context, log);
                                }
                            }, null, 5000, Timeout.Infinite);
                            isRecord = true;
                        }
                        else
                        {
                            //jsonStr = Regex.Unescape(json.ToString());
                            jsonStr = JsonConvert.SerializeObject(json);
                            if (OperationName == "撤销")
                            {
                                jsonStr = "";
                            }
                            //string appkey = "6542f75b3ae42843dec9ee36";
                            //string workcode = "ZJRM0313";
                            string workcode = KAndOSysSynTool.GetWorkCode(this.Context, this.Context.UserId.ToString());
                            if (OperationName == "反审核")
                            {
                                JSONObject unAudit = new JSONObject();
                                unAudit.Add("requestid", requestId);
                                unAudit.Add("fieldName", "status");
                                unAudit.Add("fieldValue", "1");
                                jsonStr = JsonConvert.SerializeObject(unAudit);
                            }
                            OAResult result = InvokeHelper.Post(url, jsonStr, appkey, workcode, requestId, OperationName);
                            if (result.Code == OAResultConstant.SUCCESS)
                            {
                                msg = string.Format("【{0}】{1}【{2}】成功，第三方系统返回信息：{3}！JSON信息：{4}"
                                , OperationName
                                , formName
                                , billNo
                                , JsonConvert.SerializeObject(result)
                                , jsonStr);
                                orc.Add(new OperateResult()
                                {
                                    PKValue = id
                                    ,
                                    Number = billNo
                                    ,
                                    Message = msg,
                                    MessageType = MessageType.Normal,
                                    SuccessStatus = true
                                });
                                //同步结束回写映射配置
                                long retKToOSysSynMapId = Convert.ToInt64(kToOSysSynOp["RetKToOSysSynMapId_id"]);
                                if (retKToOSysSynMapId > 0)
                                {
                                    DynamicObject retMap = KingdeeTools.GetDynamicObjectByFormIdAndId(this.Context, "qqq_KAndOSysSynMap", retKToOSysSynMapId);
                                    JSONObject obj = JSONObject.Parse(JsonUtil.Serialize(result.Data));
                                    KAndOSysSynTool.SetViewValueByReturnResult(view, retMap, obj, FPrecondition, requestId);
                                    changeOrders.Add(view.Model.DataObject);
                                }
                                returnResult = true;
                                return returnResult;
                            }
                            else
                            {
                                msg = string.Format("【{0}】{1}【{2}】同步失败，第三方系统返回信息：{3}！JSON信息：{4}"
                                , OperationName
                                , formName
                                , billNo
                                , JsonConvert.SerializeObject(result)
                                , jsonStr);
                                if (OperationName == "撤销")
                                {
                                    msg = $"OA已审批或强制撤回失败，不允许撤销！接口返回信息：{JsonConvert.SerializeObject(result)}";
                                }
                                orc.Add(new OperateResult()
                                {
                                    PKValue = id
                                    ,
                                    Number = billNo
                                    ,
                                    Message = msg,
                                    MessageType = MessageType.FatalError,
                                    SuccessStatus = false
                                });
                                returnResult = false;
                                return returnResult;
                            }

                        }
                    }
                    //else
                    //{
                    //    //撤销
                    //    if (OperationName.EqualsIgnoreCase("撤销"))
                    //    {

                    //    }
                    //}
                }
            }
            catch (Exception er)
            {
                msg = string.Format("【{0}】{1}【{2}】同步失败！错误信息：{3}"
                    , OperationName
                    , formName
                    , billNo
                    , er.Message);
                orc.Add(new OperateResult()
                {
                    PKValue = id
                    ,
                    Number = billNo
                    ,
                    Message = msg
                    ,
                    MessageType = MessageType.FatalError
                    ,
                    SuccessStatus = false
                });
                returnResult = false;
                return returnResult;
            }
            finally
            {
                if (isRecordSynLog && !isRecord)
                {
                    SyncLog log = new SyncLog();
                    log.Operation = OperationName;
                    log.FormId = formId;
                    log.FbillName = formName;
                    log.FBillNo = billNo;
                    log.Result = msg;
                    log.FOrgId = orgId;
                    log.Json = jsonStr;
                    log.IsSuccess = returnResult;
                    KingdeeTools.SaveLog(this.Context, log);
                }

            }
            return true;
        }

        private void UpAssignIsSync(string assignId)
        {
            string sql = string.Format($"/*dialect*/ UPDATE T0 SET T0.IsBeg=1 FROM T_WF_ASSIGN T0 WHERE T0.FASSIGNID='{assignId}'");
            DBServiceHelper.Execute(this.Context, sql);
        }

        private string GetTimestamp()
        {
            // 获取当前时间
            DateTime currentTime = DateTime.UtcNow;

            // Unix时间戳起始时间
            DateTime unixStartTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);

            // 计算当前时间与Unix起始时间的时间间隔
            TimeSpan elapsedTime = currentTime - unixStartTime;

            // 将时间间隔的总秒数作为Unix时间戳
            //long timestamp = (long)elapsedTime.TotalSeconds;
            long timestamp = (long)elapsedTime.TotalMilliseconds;
            return timestamp.ToString();
        }

        private void UpdatePurOrderQty(IBillView view)
        {
            var maiOrg = view.Model.DataObject["PurchaseOrgId"] as DynamicObject;
            int maiOrgId = maiOrg == null ? 0 : Convert.ToInt32(maiOrg["Id"]);
            DynamicObjectCollection rows = view.Model.DataObject["POOrderEntry"] as DynamicObjectCollection;
            for (int i = 0; i < rows.Count; i++)
            {
                var eId = Convert.ToInt32(rows[i]["Id"]);
                var mat = rows[i]["MaterialId"] as DynamicObject;
                var matNumber = mat["Number"].ToString();
                var auxPropId = rows[i]["AuxPropId"] as DynamicObject;
                var auxId = auxPropId == null ? 0 : Convert.ToInt32(auxPropId["Id"]);

                decimal invQty = GetInvQty(matNumber, maiOrgId, auxId);
                view.Model.SetValue("F_InvQty", invQty, i);

                decimal notInQty = GetNotInQty(maiOrgId, matNumber, auxId);
                view.Model.SetValue("F_NotInQty", notInQty, i);

                decimal mastPrice = GetMastPrice(maiOrgId, matNumber, auxId);
                view.Model.SetValue("F_MastPrice", mastPrice, i);

                decimal pickQty = GetPickQty(maiOrgId, matNumber, auxId);
                view.Model.SetValue("F_PickQty", pickQty, i);
            }
            //保存单据
            CreateBillView.OnlySaveBill(view, OperateOption.Create(), this.Context, this.OperationResult);
        }

        private decimal GetPickQty(int maiOrgId, string matNumber, int auxId)
        {
            string nowDate = DateTime.Now.AddDays(-7).ToString("d");
            decimal picQty = GetPicQty(maiOrgId, matNumber, auxId, nowDate);
            decimal retQty = GetRetuQty(maiOrgId, matNumber, auxId, nowDate);
            decimal othQty = GetOthQty(maiOrgId, matNumber, auxId, nowDate);
            decimal spPicQty = GetSpPicQty(maiOrgId, matNumber, auxId, nowDate);
            decimal spRetQty = GetSpRetQty(maiOrgId, matNumber, auxId, nowDate);
            decimal feedQty = GetFeedQty(maiOrgId, matNumber, auxId, nowDate);
            return picQty + spPicQty + feedQty - retQty + othQty - spRetQty;
        }

        private decimal GetFeedQty(int maiOrgId, string matNumber, int auxId, string nowDate)
        {
            string filters = $"FDOCUMENTSTATUS = 'C' AND FDATE>='{nowDate}'  AND FPrdOrgId={maiOrgId} AND FMaterialId.FNUMBER='{matNumber}' ";
            var lists = Api.ExecuteBillQuery(this.Context, "PRD_FeedMtrl", "FActualQty", filters, "FActualQty", 2000);
            if (lists.Count > 0)
            {
                var sumQty = lists.Select(x => x[0]).Sum(w => Convert.ToDecimal(w));
                return sumQty;
            }
            return 0;
        }

        private decimal GetSpRetQty(int maiOrgId, string matNumber, int auxId, string nowDate)
        {
            string filters = $"FDOCUMENTSTATUS = 'C' AND FDATE>='{nowDate}' AND FPrdOrgId={maiOrgId} AND FMaterialId.FNUMBER='{matNumber}' ";
            var lists = Api.ExecuteBillQuery(this.Context, "SP_ReturnMtrl", "FQty", filters, "FQty", 2000);
            if (lists.Count > 0)
            {
                var sumQty = lists.Select(x => x[0]).Sum(w => Convert.ToDecimal(w));
                return sumQty;
            }
            return 0;
        }

        private decimal GetSpPicQty(int maiOrgId, string matNumber, int auxId, string nowDate)
        {
            string filters = $"FDOCUMENTSTATUS = 'C' AND FDATE>='{nowDate}'  AND FPrdOrgId={maiOrgId} AND FMaterialId.FNUMBER='{matNumber}' ";
            var lists = Api.ExecuteBillQuery(this.Context, "SP_PickMtrl", "FActualQty", filters, "FActualQty", 2000);
            if (lists.Count > 0)
            {
                var sumQty = lists.Select(x => x[0]).Sum(w => Convert.ToDecimal(w));
                return sumQty;
            }
            return 0;
        }

        private decimal GetOthQty(int maiOrgId, string matNumber, int auxId, string nowDate)
        {
            string filters = $"FDOCUMENTSTATUS = 'C' AND FDATE>='{nowDate}'  AND FSTOCKORGID={maiOrgId} AND FMaterialId.FNUMBER='{matNumber}' ";
            var lists = Api.ExecuteBillQuery(this.Context, "STK_MisDelivery", "FQty", filters, "FQty", 2000);
            if (lists.Count > 0)
            {
                var sumQty = lists.Select(x => x[0]).Sum(w => Convert.ToDecimal(w));
                return sumQty;
            }
            return 0;
        }

        private decimal GetRetuQty(int maiOrgId, string matNumber, int auxId, string nowDate)
        {
            string filters = $"FDOCUMENTSTATUS = 'C' AND FDATE>='{nowDate}'  AND FPRDORGID={maiOrgId} AND FMaterialId.FNUMBER='{matNumber}' ";
            var lists = Api.ExecuteBillQuery(this.Context, "PRD_ReturnMtrl", "FQty", filters, "FQty", 2000);
            if (lists.Count > 0)
            {
                var sumQty = lists.Select(x => x[0]).Sum(w => Convert.ToDecimal(w));
                return sumQty;
            }
            return 0;
        }

        private decimal GetPicQty(int maiOrgId, string matNumber, int auxId, string nowDate)
        {
            string filters = $"FDOCUMENTSTATUS = 'C' AND FDATE>='{nowDate}'  AND FPRDORGID={maiOrgId} AND FMaterialId.FNUMBER='{matNumber}' ";
            var lists = Api.ExecuteBillQuery(this.Context, "PRD_PickMtrl", "FActualQty", filters, "FActualQty", 2000);
            if (lists.Count > 0)
            {
                var sumQty = lists.Select(x => x[0]).Sum(w => Convert.ToDecimal(w));
                return sumQty;
            }
            return 0;
        }

        private decimal GetMastPrice(int maiOrgId, string matNumber, int auxId)
        {
            string nowDate = DateTime.Now.AddDays(-180).ToString("d");
            string filters = $"FTAXPRICE>0 AND FMaterialId.FNumber='{matNumber}' AND FDocumentStatus='C'  AND FDATE>={nowDate} ";
            var lists = Api.ExecuteBillQuery(this.Context, "PUR_PurchaseOrder", "FTAXPRICE", filters, "FDATE DESC", 2000);
            if (lists.Count > 0)
            {
                return Convert.ToDecimal(lists.FirstOrDefault().FirstOrDefault());
            }
            return 0;
        }

        private decimal GetNotInQty(int maiOrgId, string matNumber, int auxId)
        {
            decimal qty = 0;
            string sql = string.Format($@"select t3.FRemainStockINQty from t_PUR_POOrder t0
            join t_PUR_POOrderEntry t1 on t1.FID=t0.FID
            join T_BD_MATERIAL t2 on t2.FMATERIALID=t1.FMATERIALID
            join T_PUR_POORDERENTRY_R t3 on t3.FENTRYID=t1.FENTRYID
            where t0.FPURCHASEORGID={maiOrgId} and t2.FNUMBER='{matNumber}'
            and t3.FRemainStockINQty>0 AND t0.FDocumentStatus='C' AND t0.FCloseStatus='A' and FCancelStatus='A' AND FMRPCloseStatus='A'");
            var res = DBServiceHelper.ExecuteDataSet(this.Context, sql).Tables[0];
            if (res.Rows.Count > 0)
            {
                qty = res.Select().Sum(s => Convert.ToDecimal(s[0]));
            }
            return qty;
        }

        private decimal GetInvQty(string matNumber, int maiOrgId, int auxId)
        {
            string filters = $"FMaterialId.FNumber='{matNumber}'  AND FBASEQTY>0 and FStockOrgId={maiOrgId}  AND FStockName NOT LIKE '%不良%' AND FStockName NOT LIKE '%废品%'";
            var lists = Api.ExecuteBillQuery(this.Context, "STK_Inventory", "FBASEQTY", filters, "FBASEQTY", 2000);
            if (lists.Count > 0)
            {
                var sumQty = lists.Select(x => x[0]).Sum(w => Convert.ToDecimal(w));
                return sumQty;
            }
            return 0;
        }

        private DynamicObject GetSatisfyConditionOp(IBillView view, List<DynamicObject> kToOSysSynOps, string operationName)
        {
            //只有一个同步操作，且前置条件为空
            if (kToOSysSynOps.Count() == 1 && kToOSysSynOps.First()["FPrecondition"].IsNullOrEmptyOrWhiteSpace())
            {
                return kToOSysSynOps.First();
            }
            List<DynamicObject> successObjs = new List<DynamicObject>();
            //存在多个同步操作，循环所有
            foreach (var kToOSysSynOp in kToOSysSynOps)
            {
                string pyExpression = Convert.ToString(kToOSysSynOp["FPrecondition"]);
                var result = KAndOSysSynTool.analysisConditionalExpression(view, 0, "", pyExpression);
                bool isSuccess = false;
                Boolean.TryParse(Convert.ToString(result), out isSuccess);
                if (isSuccess)
                {
                    successObjs.Add(kToOSysSynOp);
                }
            }
            if (successObjs.Count() == 1)
            {
                return successObjs.First();
            }
            else if (successObjs.Count() > 1)
            {
                List<string> errs = new List<string>();
                foreach (var successObj in successObjs)
                {
                    string id = Convert.ToString(successObj["id"]);
                    string pyExpression = Convert.ToString(successObj["FPrecondition"]);
                    string err = string.Format("【{0}】前置条件【{1}】", id, pyExpression);
                    errs.Add(err);
                }
                string errMsg = string.Format("获取到{0}【{1}】有效操作设置有多个：{2}"
                    , view.BusinessInfo.GetForm().Name
                    , operationName
                    , string.Join(",\r\n", errs)
                    ); ;
                throw new Exception(errMsg);
            }
            else
            {
                return null;
            }
        }
    }
}
